using UnityEngine;
using System.Collections;

/// \class  gkUtilitySculpting
/// \brief  Mesh modification functions
public class gkUtilitySculpting 
{
	/// \brief  Apply a sphere cone slice push to the mesh surface
	static public void ApplySphereRadialPush(Mesh a_rMesh, Vector3 a_f3PushCenter, float a_fPushPower, float a_fPushRadius, 
	                                         float a_fMinimumRadius, float a_fMaximumRadius)
	{
		float fPushCenterHeight;
		float fPushCenterAngle;
		
		// Compute the push center height
		fPushCenterHeight = a_f3PushCenter.magnitude;
	
		if(fPushCenterHeight != 0.0f)
		{
			// Compute the	
			fPushCenterAngle = Mathf.Rad2Deg * Mathf.Atan(a_fPushRadius/fPushCenterHeight);
			ApplySphereConeSlicePush(a_rMesh, a_f3PushCenter, a_fPushPower, fPushCenterAngle, a_fMinimumRadius, a_fMaximumRadius);
		}
	}
	
	/// \brief  Apply a sphere cone slice push to the mesh surface
	static public void ApplySphereRadialPush(Vector3[] a_rVertices, Vector3 a_f3PushCenter, float a_fPushPower, float a_fPushRadius, 
	                                         float a_fMinimumRadius, float a_fMaximumRadius)
	{
		float fPushCenterHeight;
		float fPushCenterAngle;
		
		// Compute the push center height
		fPushCenterHeight = a_f3PushCenter.magnitude;
	
		if(fPushCenterHeight != 0.0f)
		{
			// Compute the	
			fPushCenterAngle = Mathf.Rad2Deg * Mathf.Atan(a_fPushRadius/fPushCenterHeight);
			ApplySphereConeSlicePush(a_rVertices, a_f3PushCenter, a_fPushPower, fPushCenterAngle, a_fMinimumRadius, a_fMaximumRadius);
		}
	}
	
	/// \brief  Apply a sphere cone slice push to the mesh surface
	static public void ApplySphereConeSlicePush(Mesh a_rMesh, Vector3 a_f3PushCenter, float a_fPushPower, float a_fPushConeAngle, 
	                                            float a_fMinimumRadius, float a_fMaximumRadius)
	{
		Vector3[] rVertices = a_rMesh.vertices;
			
		// Push vertices in the sphere
		ApplySphereConeSlicePush(rVertices, a_f3PushCenter, a_fPushPower, a_fPushConeAngle,
		                         a_fMinimumRadius, a_fMaximumRadius);
		
		// Update the mesh vertices
		a_rMesh.vertices = rVertices;
		
		// Update the mesh
		a_rMesh.RecalculateNormals();
		a_rMesh.RecalculateBounds();
	}
	
	/// \brief  Apply a sphere cone slice push to the mesh surface
	static public void ApplySphereConeSlicePush(Vector3[] a_rVertices, Vector3 a_f3PushCenter, float a_fPushPower, float a_fPushConeAngle, 
	                                            float a_fMinimumRadius, float a_fMaximumRadius)
	{
		// Push vertices in the sphere
		for(int i=0; i < a_rVertices.Length; i++)
		{
			Vector3 f3Vertex;
			Vector3 f3VertexNormal;
			float fVertexAngleDistanceFromPushCenter;
			float fVertexDistanceFromCenter;
			
			// Get the vertex
			f3Vertex = a_rVertices[i];
			
			// Compute the distance between the push position and the current vertex
			fVertexAngleDistanceFromPushCenter = Vector3.Angle(a_f3PushCenter, f3Vertex);
			
			// Only consider the vertex that are in the push cone
			if(fVertexAngleDistanceFromPushCenter <= a_fPushConeAngle)
			{
				// Compute the vertex normal
				f3VertexNormal = f3Vertex;
				f3VertexNormal.Normalize();
				
				// Push the vertex
				f3Vertex = f3Vertex - a_fPushPower * f3VertexNormal;
				
				// verify isn't too deep in the sphere
				fVertexDistanceFromCenter = f3Vertex.magnitude;
				if(fVertexDistanceFromCenter < a_fMinimumRadius)
				{
					f3Vertex = f3VertexNormal * a_fMinimumRadius;
				}
				else if(fVertexDistanceFromCenter > a_fMaximumRadius)
				{
					//f3Vertex = f3VertexNormal * a_fMaximumRadius;
				}
				// Update the vertex
				a_rVertices[i] = f3Vertex;
			}
		}
	} 
}
